%% Author: f355
%% Created: 07.03.2010
%% Description: TODO: Add description to generate
-module(ddc_gen).

%%
%% Include files
%%
-include("ddc_settings.hrl").

%%
%% Exported Functions
%%
-compile(export_all).
-export([gen_from_word/1, gen_from_sentence/1]).

%%
%% API Functions
%%

%% Generate sentence using initial word
gen_from_word(Word) ->
    gen_from_sentence([Word]).

gen_from_seed(Seed) ->
    

    %% Spawn two worker processes to expand initial phrase back and forth
    Pid_f = spawn(?MODULE, run_expand, [self(), Seed, f]),
    Pid_b = spawn(?MODULE, run_expand, [self(), Seed, b]),

    %% Receive results of expanding
    Res_f=receive_expand(Pid_f, Seed),
    Res_b=receive_expand(Pid_b, Seed),

    %% Compose one array from received results (discarding Seed from right part)
    Res=Res_b++lists:nthtail(length(Seed), Res_f),

    %% Final result
    {ok, Res}.

%% Generate sentence using list of words (reply)
gen_from_sentence(Sentence) ->
    gen_from_sentence(go, lists:sort(fun(A, B) -> length(A)>length(B) end, lists:usort(Sentence))).
%    Sentence.

gen_from_sentence(go, [Word|Rest]) ->
    case get_seed(Word) of
	{ok, Seed} -> gen_from_seed(Seed);
	_ ->
%	    io:write({running, Rest}),
	    gen_from_sentence(go, Rest)
    end;

gen_from_sentence(go, _) ->
    case get_random_seed() of
	{ok, Seed} -> gen_from_seed(Seed);
	Other -> Other
    end.
	    

%%
%% Local Functions
%%

%% Get initial seed for generating, given one word.
%% @TODO Get random seed in case when word is empty or nothing is found.
get_seed(Word) ->
    case ddc_db:run_query(fun() -> ddc_db:read_random(words, Word, f) end, dirty) of
	{ok, Phrase} -> {ok, [Word|Phrase]};
	_ -> 
	    case ddc_db:run_query(fun() -> ddc_db:read_random(words, Word, b) end, dirty) of
		{ok, Phrase} -> {ok, Phrase++[Word]};
		_ -> {error, no_seed}
	    end
    end.

get_random_seed() ->
    case ddc_db:run_query(fun() -> ddc_db:random_key(words) end, dirty) of
	{ok, Word} -> get_seed(Word);
	Other -> Other
    end.

%% Helper function to be used in spawn/3.
%% Runs calculations and passes the result to parent process.
run_expand(Pid, Sentence, Dir) ->
    Result=expand(Sentence, Dir),
    Pid!{self(),Result}.

%% Helper function to receive the result from spawned process. 
%% @TODO Adjust timeout under real workload (or make configurable option)
receive_expand(Pid, Default) ->
    receive
	{Pid, {ok, Result}} -> Result;
	{Pid, _} -> Default
    after 1000 -> Default
    end.

%% Essential part of generation: expanding seed.
expand(Sentence, f) ->
    case ddc_db:run_query(fun() -> ddc_db:read_random(phrases, lists:nthtail(length(Sentence)-?CARDINALITY, Sentence), f) end, dirty) of
	{ok, Word} -> expand(Sentence++[Word], f);
	_ -> {ok, Sentence}
    end;

expand(Sentence, b) ->
    case ddc_db:run_query(fun() -> ddc_db:read_random(phrases, lists:sublist(Sentence, ?CARDINALITY), b) end, dirty) of
	{ok, Word} -> expand([Word|Sentence], b);
	_ -> {ok, Sentence}
    end.
